"""
 * Copyright (c) KylinSoft  Co., Ltd. 2024.All rights reserved.
 * PilotGo-plugin licensed under the Mulan Permissive Software License, Version 2.
 * See LICENSE file for more details.
 * Author: wangqingzheng <wangqingzheng@kylinos.cn>
 * Date: Mon Feb 26 11:15:07 2024 +0800
"""
import logging
from rest_framework import status, viewsets
# Create your views here.
from appStore.fio.models import Fio
from appStore.fio.serializers import FioSerializer
from appStore.project.models import Project
from appStore.utils.common import json_response, get_error_message, get_analyze_data

log = logging.getLogger('kytuninglog')

class FioViewSet(viewsets.ModelViewSet):
    """
    fio数据管理
    """
    queryset = Fio.objects.all().order_by('id')
    serializer_class = FioSerializer

    def get_unit(self, data):
        # value是值，unit是单位
        unit = data.split("".join(filter(lambda s: s in '0123456789.', data)))[-1]
        if unit:
            value = data.split(unit)[0]
        else:
            value = data
        return value, unit

    def get_bw_unit(self,data):
        unit1 = data.split('(')[0].split(
            "".join(filter(lambda s: s in '0123456789.', data.split('(')[0])))[-1]
        # 这里是kB/s)，后面就不需要再次拼接了
        unit2 = data.split('(')[-1].split(
            "".join(filter(lambda s: s in '0123456789.', data.split('(')[-1])))[-1]
        value1 = float(data.split('(')[0].split(unit1)[0])
        value2 = float(data.split('(')[1].split(unit2)[0])
        return value1, value2, unit1, unit2

    def get_data(self, serializer_, datas, title_index, column_index, base_column_index):
        serializer = self.get_serializer(serializer_, many=True)
        temp_datas = []
        groups = set([d.mark_name for d in serializer_])
        if not groups or len(groups) == 1:
            if not groups:
                # 当没有数据时
                # 原始数据部分
                datas[0]['column' + str(column_index)] = 'Fio#' + str(title_index)
                datas[1]['column' + str(column_index)] = None
                datas[2]['column' + str(column_index)] = None
                datas[3]['column' + str(column_index)] = None
                # 初始化所有数据为None
                for i in range(4, len(datas)):
                    datas[i]['column' + str(column_index)] = None
                column_index += 1
                title_index += 1
            else:
                # 当只有一组数据时
                # 原始数据部分
                for data in serializer.data:
                    data = {'rw': data['rw'] + '(' + str(data['bs'] + ')'),
                            'bs': data['bs'],
                            'io': data['io'],
                            'iops': data['iops'],
                            'bw': data['bw'], }
                    temp_datas.append(data)
                # 先增加表头的内容
                datas[0]['column' + str(column_index)] = 'Fio#' + str(title_index)
                datas[1]['column' + str(column_index)] = Project.objects.filter(env_id=serializer.data[0]['env_id']).first().project_name
                datas[2]['column' + str(column_index)] = serializer.data[0]['execute_cmd']
                datas[3]['column' + str(column_index)] = serializer.data[0]['modify_parameters']

                for i in range(4,len(datas)):
                    datas[i]['column' + str(column_index)] = None
                for value in temp_datas:
                    # 判断comparsion_datas数据中的rw字段和datas中的rw（column）字段相同，则在datas中增加值
                    for index, data_ in enumerate(datas):
                        if data_['column1'] == value['rw']:
                            # 在datas中增加对比数据
                            datas[index]['column' + str(column_index)] = value['bs']
                            datas[index + 1]['column' + str(column_index)] = value['io']
                            datas[index + 2]['column' + str(column_index)] = value['iops']
                            datas[index + 3]['column' + str(column_index)] = value['bw']
                            break
                column_index += 1
                title_index += 1
            # 平均数据
            title = '平均值(基准数据)' if not base_column_index else '平均值'
            datas[0]['column' + str(column_index)] = title
            datas[1]['column' + str(column_index)] = datas[1]['column' + str(column_index - 1)]
            datas[2]['column' + str(column_index)] = ''
            datas[3]['column' + str(column_index)] = ''
            for i in range(4, len(datas)):
                datas[i]['column' + str(column_index)] = None
            for value in temp_datas:
                for index, data_ in enumerate(datas):
                    if data_['column1'] == value['rw']:
                        # 在datas中增加对比数据
                        datas[index]['column' + str(column_index)] = None
                        datas[index + 1]['column' + str(column_index)] = None
                        datas[index + 2]['column' + str(column_index)] = value['iops']
                        datas[index + 3]['column' + str(column_index)] = None
                        break
            column_index += 1
        else:
            # 多组数据
            bs_size = set([d['bs'] for d in serializer.data])
            rw_types = set([d['rw'] for d in serializer.data])
            new_datas = []
            average_datas = []
            for test_type in bs_size:
                for rw_type in rw_types:
                    data_ = serializer_.filter(bs=test_type).filter(rw=rw_type)
                    if data_:
                        new_datas.append(data_)
            # new_datas是12组数据
            for data_ in new_datas:
                iops_list = [d.iops for d in data_ if d.iops is not None]
                # 计算iops的平均值
                iops = 0
                for iops_ in iops_list:
                    value, iops_unit = self.get_unit(iops_)
                    iops += float(value)
                iops = "%.2f" % (iops / len(iops_list))
                data = {'rw': data_[0].rw + '(' + str(data_[0].bs + ')'),
                        'bs': None,
                        'io': None,
                        'iops': iops,
                        'bw': None, }
                average_datas.append(data)
            # 基准数据和对比数据的全部数据
            for mark_name in groups:
                # group_data找到属于同一组的数据在组装成json数据
                group_data = []
                temp_mark_datas = serializer_.filter(mark_name=mark_name)
                # 先增加头部的内容
                datas[0]['column' + str(column_index)] = 'Fio#' + str(title_index)
                datas[1]['column' + str(column_index)] = Project.objects.filter(env_id=temp_mark_datas[0].env_id).first().project_name
                datas[2]['column' + str(column_index)] = temp_mark_datas[0].execute_cmd
                datas[3]['column' + str(column_index)] = temp_mark_datas[0].modify_parameters
                for data in temp_mark_datas:
                    data = {'rw': data.rw + '(' + str(data.bs + ')'),
                            'bs': data.bs,
                            'io': data.io,
                            'iops': data.iops,
                            'bw': data.bw, }
                    group_data.append(data)
                # 增加对比数据部分
                # 先初始化所有对比数据为空
                for i in range(4, len(datas)):
                    datas[i]['column' + str(column_index)] = None
                for value in group_data:
                    # 判断comparsion_datas数据中的rw字段和datas中的rw（column）字段相同，则在datas中增加值对比值
                    for index, data_ in enumerate(datas):
                        if index > 2:
                            if data_['column1'] == value['rw']:
                                # 在datas中增加对比数据
                                datas[index]['column' + str(column_index)] = value['bs']
                                datas[index + 1]['column' + str(column_index)] = value['io']
                                datas[index + 2]['column' + str(column_index)] = value['iops']
                                datas[index + 3]['column' + str(column_index)] = value['bw']
                                break
                column_index += 1
                title_index += 1
            title = '平均值(基准数据)' if not base_column_index else '平均值'
            # 基准数据和对比数据的平均数据
            datas[0]['column' + str(column_index)] = title
            datas[1]['column' + str(column_index)] = datas[1]['column' + str(column_index - 1)]
            datas[2]['column' + str(column_index)] = ""
            datas[3]['column' + str(column_index)] = ""
            for i in range(4, len(datas)):
                datas[i]['column' + str(column_index)] = None
            for value in average_datas:
                for index, data_ in enumerate(datas):
                    if index > 2:
                        if data_['column1'] == value['rw']:
                            # 在datas中增加对比数据
                            datas[index]['column' + str(column_index)] = value['bs']
                            datas[index + 1]['column' + str(column_index)] = value['io']
                            datas[index + 2]['column' + str(column_index)] = value['iops']
                            datas[index + 3]['column' + str(column_index)] = value['bw']
                            break
            column_index += 1

        # 记录基准数据
        if not base_column_index:
            base_column_index = column_index - 1
        else:
            # 对比值
            datas[0]['column' + str(column_index)] = '对比值'
            datas[1]['column' + str(column_index)] = ''
            datas[2]['column' + str(column_index)] = ''
            datas[3]['column' + str(column_index)] = ''
            # 获取到最后一组数据、处理数据 #计算全部的对比值
            # 只计算iops的对比值
            for i in range(4, len(datas)):
                value = datas[i]['column' + str(column_index - 1)]  # 最后一组数据
                base_value = datas[i]['column' + str(base_column_index)]  # base数据
                if value is not None and base_value is not None:
                    import re
                    if bool(re.match(r'^[0-9.]+$', value)):
                        datas[i]['column' + str(column_index)] = "%.2f%%" % ((float(value) - float(base_value)) / float(base_value) * 100) if value is not None and base_value is not None else None
                    else:
                        datas[i]['column' + str(column_index)] = None
                else:
                    datas[i]['column' + str(column_index)] = None
            column_index += 1
        return datas, title_index, column_index, base_column_index


    def get_left_data(self, serializer_):
        datas = []
        # groups = set([d.mark_name for d in serializer_])
        # 如果使用group的方式，set时无序的，当其它数据部分内容没有数据时旧会导致全都不展示对应的数据，所有这里想到好一点的方法就是
        # 时用0-0，首先就要确保0-0的数据必须时最全的
        filter_datas = serializer_.filter(mark_name='0-0')
        for data in filter_datas:
            data_ = {'rw': data.rw + '(' + str(data.bs + ')'),
                    'bs': data.bs,
                    'io': data.io,
                    'iops': data.iops,
                    'bw': data.bw, }
            datas.append(data_)
        temp_data = []
        for value in datas:
            data = [{'column1': value['rw'], 'column2': 'bs'},
                    {'column1': value['rw'], 'column2': 'io'},
                    {'column1': value['rw'], 'column2': 'iops'},
                    {'column1': value['rw'], 'column2': 'bw'}]
            temp_data.extend(data)
        others = [{'column1': 'Fio', 'column2': '', },
                  {'column1': '项目名称', 'column2': ''},
                  {'column1': '执行命令', 'column2': ''},
                  {'column1': '修改参数', 'column2': ''}]
        new_data = others + temp_data
        return new_data

    def list(self, request, *args, **kwargs):
        env_id = request.GET.get('env_id')
        comparsionIds = request.GET.get('comparsionIds')
        comparsionIds = comparsionIds.split(',')
        base_queryset = Fio.objects.filter(env_id=env_id).all()
        datas = self.get_left_data(base_queryset)
        title_index = 1
        column_index = 3
        base_column_index = ''
        datas, title_index, column_index, base_column_index = self.get_data(base_queryset, datas, title_index, column_index, base_column_index)
        if comparsionIds != ['']:
            # 处理对比数据
            for comparativeId in comparsionIds:
                comparsion_queryset = Fio.objects.filter(env_id=comparativeId).all()
                datas, title_index, column_index, base_column_index = self.get_data(comparsion_queryset, datas, title_index, column_index, base_column_index)
        analyze_data = get_analyze_data(datas, 'fio')
        all_datas = {'datas': datas, 'analyze_data': analyze_data}
        return json_response(all_datas, status.HTTP_200_OK, '列表')

    def create(self, request, *args, **kwargs):
        serializer_fio_errors = []
        error_message = []
        for k, fio_json in request.__dict__['data_fio'].items():
            data_fio = {}
            if k.lower().startswith('fio'):
                data_fio['env_id'] = request.__dict__['data_fio']['env_id']
                data_fio['execute_cmd'] = fio_json.get('execute_cmd')
                data_fio['modify_parameters'] = fio_json.get('modify_parameters')
                data_fio['mark_name'] = k[-3:]
                data_fio['rw'] = fio_json['rw']
                data_fio['bs'] = fio_json['items']['bs']
                data_fio['io'] = fio_json['items']['io']
                data_fio['iops'] = fio_json['items']['iops']
                data_fio['bw'] = fio_json['items']['bw']
                data_fio = {key: value if not isinstance(value, str) or value != '' else None for key, value in
                               data_fio.items()}
                serializer_fio = FioSerializer(data=data_fio)
                if serializer_fio.is_valid():
                    self.perform_create(serializer_fio)
                    continue
                log.info('fio数据存储错误 ：%s，'%serializer_fio.errors)
                log.info('fio存储数据为 ：%s，'%data_fio)
                return json_response(serializer_fio.errors, status.HTTP_400_BAD_REQUEST,
                                     get_error_message(serializer_fio))
        if serializer_fio_errors:
            print(serializer_fio_errors, "fio")
            return json_response(serializer_fio_errors, status.HTTP_400_BAD_REQUEST, error_message)
        else:
            return
